home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 June
/
EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso
/
earcd
/
utilsys
/
rss14gmd.lha
/
RSys_1.4gmd
/
C
/
SaveWindow.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-04
|
21KB
|
967 lines
/*
***************************************************************************
*
* Datei:
* RSysSaveWindow.c
*
* Inhalt:
*
* --- Globale Routinen ---
*
* void SaveWindows ( void );
*
* --- Lokale Routinen ---
*
* static BYTE PutANNO ( IFFHANDLE *Handle );
* static BYTE PutBMHD ( IFFHANDLE *Handle , WINDOW *Window , UBYTE Compression );
* static BYTE PutBODY ( IFFHANDLE *Handle , BITMAP *BitMap , UBYTE Compression );
* static BYTE PutCAMG ( IFFHANDLE *Handle , VIEWPORT *VPort );
* static BYTE PutCMAP ( IFFHANDLE *Handle , VIEWPORT *VPort );
* static BYTE SaveWindow ( STRPTR Name , WINDOW *Window );
* static int OpenSaveAWindowWindow ( void );
* static LONG PackRow ( PLANEPTR *SourcePtr , PLANEPTR Destination , LONG RowSize );
* static PLANEPTR PutDump ( PLANEPTR Destination , LONG Count );
* static PLANEPTR PutRun ( PLANEPTR Destination , LONG Count , WORD Char );
* static void CreateWinList ( int count );
* static void ResetWinList ( void );
*
* Bemerkungen:
* Erzeugen einer IFF-Datei aus einem Window.
*
* Erstellungsdatum:
* 07-Jan-93 Rolf Böhme
*
* Änderungen:
* 07-Jan-93 Rolf Böhme Erstellung
*
***************************************************************************
*/
#include "RSys.h"
#include "protos.h"
/*
* Diese Routinen habe ich wieder mal aus der
* "Quellen-Fundgrube" von TERM entnommen. Danke Olaf! Aber
* einiges war leider falsch :-)
*/
/* Local packer data. */
static LONG PackedBytes;
static BYTE Buffer[MAXDAT + 1];
/* PutDump( PLANEPTR Destination, LONG Count):
* Output a byte dump.
*/
static PLANEPTR
PutDump (PLANEPTR Destination, LONG Count)
{
PLANEPTR Source = (PLANEPTR) Buffer;
*Destination++ = Count - 1;
PackedBytes += Count + 1;
while (Count--)
*Destination++ = *Source++;
return Destination;
}
/* PutRun( PLANEPTR Destination,LONG Count,WORD Char):
* Output a byte run.
*/
static PLANEPTR
PutRun (PLANEPTR Destination, LONG Count, WORD Char)
{
*Destination++ = -(Count - 1);
*Destination++ = Char;
PackedBytes += 2;
return Destination;
}
/* PackRow(PLANEPTR *SourcePtr, PLANEPTR Destination,LONG RowSize):
* Pack a row of bitmap data using ByteRun compression,
* based on the original "EA IFF 85" pack.c example code.
*/
static LONG
PackRow (PLANEPTR * SourcePtr, PLANEPTR Destination, LONG RowSize)
{
PLANEPTR Source = *SourcePtr;
WORD Buffered = 1, RunStart = 0;
BYTE Mode = DUMP, LastChar, Char;
PackedBytes = 0;
Buffer[0] = LastChar = Char = *Source++;
RowSize--;
while (RowSize--)
{
Buffer[Buffered++] = Char = *Source++;
if (Mode)
{
if ((Char != LastChar) || (Buffered - RunStart > MAXRUN))
{
Destination = PutRun (Destination, Buffered - 1 - RunStart, LastChar);
Buffer[0] = Char;
Buffered = 1;
RunStart = 0;
Mode = DUMP;
}
}
else
{
if (Buffered > MAXDAT)
{
Destination = PutDump (Destination, Buffered - 1);
Buffer[0] = Char;
Buffered = 1;
RunStart = 0;
}
else
{
if (Char == LastChar)
{
if (Buffered - RunStart >= MINRUN)
{
if (RunStart)
Destination = PutDump (Destination, (LONG) RunStart);
Mode = RUN;
}
else
{
if (!RunStart)
Mode = RUN;
}
}
else
RunStart = Buffered - 1;
}
}
LastChar = Char;
}
if (Mode)
PutRun (Destination, Buffered - RunStart, LastChar);
else
PutDump (Destination, (LONG) Buffered);
*SourcePtr = Source;
return PackedBytes;
}
/* PutANNO(IFFHANDLE *Handle):
* Output `ANNO' chunk.
*/
static BYTE
PutANNO (IFFHANDLE * Handle)
{
WORD Len;
Len = strlen (&gmdv[1]);
/* Push the `ANNO' chunk on the stack. */
if (!PushChunk (Handle, 0, ID_ANNO, (long) Len))
{
/* Write the creator string. */
if (WriteChunkBytes (Handle, &gmdv[1], (long) Len) == Len)
{
/* Pop the `ANNO' chunk. */
if (!PopChunk (Handle))
return TRUE;
}
}
return FALSE;
}
/* PutBMHD():
* Output `BMHD' chunk.
*/
static BYTE
PutBMHD (IFFHANDLE * Handle, WINDOW * Window, UBYTE Compression)
{
DISPLAYINFO DisplayInfo;
/* Get the display aspect ratio. */
if (GetDisplayInfoData (NULL,
(APTR) & DisplayInfo,
sizeof (DISPLAYINFO),
DTAG_DISP,
GetVPModeID (&Window->WScreen->ViewPort)))
{
RSYS_BitMapHeader Header;
/* Fill in the bitmap header. */
Header.w = Window->Width;
Header.h = Window->Height;
Header.pageWidth = Window /*-> WScreen*/ ->Width;
Header.pageHeight = Window /*-> WScreen*/ ->Height;
Header.x = Window->LeftEdge;
Header.y = Window->TopEdge;
Header.nPlanes = Window /*-> WScreen*/ ->RPort->BitMap->Depth;
Header.masking = mskNone;
Header.compression = Compression;
Header.pad1 = 0;
Header.transparentColor = 0;
Header.xAspect = DisplayInfo.Resolution.x;
Header.yAspect = DisplayInfo.Resolution.y;
/* Push the `BMHD' chunk on the stack. */
if (!PushChunk (Handle, 0, ID_BMHD, sizeof (RSYS_BitMapHeader)))
{
/* Write the bitmap header. */
if (WriteChunkBytes (Handle, &Header, sizeof (RSYS_BitMapHeader)) == sizeof (RSYS_BitMapHeader))
{
/* Pop the `BMHD' chunk. */
if (!PopChunk (Handle))
return TRUE;
}
}
}
return FALSE;
}
/* PutCMAP(IFFHANDLE *Handle,VIEWPORT *VPort):
* Output `CMAP' chunk, only 4-bit colour s
* are supported so far.
*/
static BYTE
PutCMAP (IFFHANDLE * Handle, VIEWPORT * VPort)
{
/* Push the `CMAP' chunk on the stack. */
if (!PushChunk (Handle, 0, ID_CMAP, 3 * VPort->ColorMap->Count))
{
RSYS_ColorRegister Colour;
LONG i;
ULONG Value, R, G, B;
/* Read and convert all the
* ColorMap entries (4 bit colour
* components only).
*/
for (i = 0; i < VPort->ColorMap->Count; i++)
{
/* Read colour value. */
Value = GetRGB4 (VPort->ColorMap, i);
/* Split the value into components. */
R = (Value >> 8) & 0xF;
G = (Value >> 4) & 0xF;
B = (Value) & 0xF;
/* Store the colour components. */
Colour.red = (R << 4) | R;
Colour.green = (G << 4) | G;
Colour.blue = (B << 4) | B;
/* Write the colours. */
if (WriteChunkBytes (Handle, &Colour, 3) != 3)
return (FALSE);
}
/* Pop the `CMAP' chunk. */
if (!PopChunk (Handle))
return TRUE;
}
return FALSE;
}
/* PutCAMG(IFFHANDLE *Handle,VIEWPORT *VPort):
* Output `CAMG' chunk.
*/
static BYTE
PutCAMG (IFFHANDLE * Handle, VIEWPORT * VPort)
{
if (!PushChunk (Handle, 0, ID_CAMG, sizeof (ULONG)))
{
ULONG ViewModes = GetVPModeID (VPort), ulongsize = sizeof (ULONG);
if (WriteChunkBytes (Handle, &ViewModes, ulongsize) == ulongsize)
{
if (!PopChunk (Handle))
return TRUE;
}
}
return FALSE;
}
/* PutBODY(IFFHANDLE *Handle)
* Output `BODY' chunk.
*/
static BYTE
PutBODY (IFFHANDLE * Handle, BITMAP * BitMap, UBYTE Compression)
{
BYTE Success = FALSE;
PLANEPTR *Planes;
/* Allocate temporary bitplane pointers. */
if (Planes = (PLANEPTR *) MyAllocVec (BitMap->Depth * sizeof (PLANEPTR *), MEMF_ANY | MEMF_CLEAR, NO_KILL))
{
LONG i;
/* Copy the bitplane pointers. */
for (i = 0; i < BitMap->Depth; i++)
Planes[i] = BitMap->Planes[i];
/* Are we to compress the data? */
if (Compression == cmpByteRun1)
{
PLANEPTR PackBuffer;
/* Allocate line compression buffer. */
if (PackBuffer = (PLANEPTR) MyAllocVec (BitMap->BytesPerRow * 2, MEMF_ANY, NO_KILL))
{
/* Push the `BODY' chunk on the stack. */
if (!PushChunk (Handle, 0, ID_BODY, IFFSIZE_UNKNOWN))
{
LONG PackedBytes, j;
/* So far, we are quite successful,
* any write access to fail will
* cause `Success' to drop to FALSE.
*/
Success = TRUE;
/* Compress all the rows. */
for (i = 0; Success && i < BitMap->Rows; i++)
{
/* Compress all the planes. */
for (j = 0; Success && j < BitMap->Depth; j++)
{
/* Do the compression. */
PackedBytes = PackRow (&Planes[j], PackBuffer, (LONG) BitMap->BytesPerRow);
/* Write the compressed data. */
if (WriteChunkBytes (Handle, PackBuffer, PackedBytes) != PackedBytes)
Success = FALSE;
}
}
/* Pop the `BODY' chunk. */
if (PopChunk (Handle))
Success = FALSE;
}
/* Free the line compression buffer. */
MyFreeVec (PackBuffer);
}
}
else
{
/* Push the `BODY' chunk on the stack. */
if (!PushChunk (Handle, 0, ID_BODY, IFFSIZE_UNKNOWN))
{
LONG j;
/* So far, we are quite successful,
* any write access to fail will
* cause `Success' to drop to FALSE.
*/
Success = TRUE;
/* Compress all the rows. */
for (i = 0; Success && i < BitMap->Rows; i++)
{
/* Compress all the planes. */
for (j = 0; Success && j < BitMap->Depth; j++)
{
/* Write the row. */
if (WriteChunkBytes (Handle, Planes[j], (long) BitMap->BytesPerRow) != BitMap->BytesPerRow)
Success = FALSE;
else
Planes[j] += BitMap->BytesPerRow;
}
}
/* Pop the `BODY' chunk. */
if (PopChunk (Handle))
Success = FALSE;
}
}
/* Free the temporary bitplane pointers. */
MyFreeVec (Planes);
}
/* Return the result. */
return Success;
}
/* SaveWindow(STRPTR Name,WINDOW *Window):
* Save the contents of a window to a file.
*/
static BYTE
SaveWindow (STRPTR Name, WINDOW * Window)
{
RASTPORT *RPort;
BYTE Success = FALSE, NewFile = FALSE;
if (IFFParseBase = OpenLibrary ((STRPTR) "iffparse.library", 0))
{
/* Allocate a dummy rastport, we will need only
* to copy the contents of the window into the
* bitmap.
*/
if (RPort = (RASTPORT *) MyAllocVec (sizeof (RASTPORT), MEMF_ANY, NO_KILL))
{
BITMAP *BitMap;
/* Initialize the rastport with defaults. */
InitRastPort (RPort);
/* Allocate a bitmap. */
if (BitMap = (BITMAP *) MyAllocVec (sizeof (BITMAP), MEMF_ANY, NO_KILL))
{
WORD i;
/* Put it into the rastport. */
RPort->BitMap = BitMap;
/* Initialize it with the window dimensions. */
/*
* An dieser Stelle ist der RastPort des Fensters
* zu nehmen, NICHT der des Screens, zu dem das
* Fenster gehört!
*/
InitBitMap (BitMap,
(long) Window->RPort->BitMap->Depth,
(long) (Window->Width),
(long) Window->Height);
/* Flag success so any allocation
* to fail in the bitplane allocation
* loop will indicate failure.
*/
Success = TRUE;
/* Allocate all the bitplanes necessary. */
for (i = 0; Success && i < BitMap->Depth; i++)
{
if (!(BitMap->Planes[i] = AllocRaster ((long) Window->Width, (long) Window->Height)))
Success = FALSE;
}
/* Did we get all the planes we wanted? */
if (Success)
{
IFFHANDLE *Handle;
/* Copy the window contents to the
* local bitmap.
*/
if (NOT (Window->Flags & WFLG_BACKDROP))
WindowToFront (Window);
Delay (10);
/*
* ClipBlit() arbeitet nicht korrekt! Ich habe
* die Routine durch BltBitMap() ersetzt
*/
/*
* ClipBlit(Window -> RPort,0,0,RPort,0,0,(long)Window -> Width,(long)Window -> Height,0xC0);
*/
BltBitMap (Window->RPort->BitMap,
(long) Window->LeftEdge, (long) Window->TopEdge, BitMap,
0, 0, (long) Window->Width, (long) Window->Height, 0xC0, 0xFF, NULL);
/* Reset the success indicator. */
Success = FALSE;
/* Allocate an iff handle. */
if (Handle = AllocIFF ())
{
/* Open a file for write access. */
if (Handle->iff_Stream = Open (Name, MODE_NEWFILE))
{
/* Remember that we succeeded
* in creating a new file.
*/
NewFile = TRUE;
/* Tell iffparse.library that it's
* a plain AmigaDOS file handle.
*/
InitIFFasDOS (Handle);
/* Open the file for writing. */
if (!OpenIFF (Handle, IFFF_WRITE))
{
/* Push parent chunk on the
* stack.
*/
if (!PushChunk (Handle, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN))
{
/* Output all the chunk data. */
if (PutANNO (Handle))
{
UBYTE Compression;
/* Don't compress the bitmap if
* isn't really worth it.
*/
if (BitMap->BytesPerRow > 4)
Compression = cmpByteRun1;
else
Compression = cmpNone;
if (PutBMHD (Handle, Window, Compression))
{
if (PutCMAP (Handle, &Window->WScreen->ViewPort))
{
if (PutCAMG (Handle, &Window->WScreen->ViewPort))
{
if (PutBODY (Handle, BitMap, Compression))
{
/* Pop the parent chunk
* from the stack.
*/
if (!PopChunk (Handle))
Success = TRUE;
}
}
}
}
}
}
/* Close the iff handle. */
CloseIFF (Handle);
}
/* Close the file. */
if (!Close (Handle->iff_Stream))
Success = FALSE;
}
/* Free the iff handle. */
FreeIFF (Handle);
}
}
/* Free all bitplanes. */
for (i = 0; i < BitMap->Depth; i++)
{
if (BitMap->Planes[i])
FreeRaster (BitMap->Planes[i], (long) Window->Width, (long) Window->Height);
}
/* Free the bitmap. */
MyFreeVec (BitMap);
}
/* Free the rastport. */
MyFreeVec (RPort);
}
/* If successful, clear the `executable' bit. */
if (Success)
SetProtection (Name, FIBF_EXECUTE);
else
{
/* Delete the remains of the file. */
if (NewFile)
DeleteFile (Name);
}
CloseLibrary (IFFParseBase);
}
else
Success = FALSE;
/* Return the result. */
return Success;
}
RSYS_winlist *windows = NULL;
LIST WinList;
static WINDOW *SaveAWindowWnd = NULL;
static GADGET *SaveAWindowGList = NULL;
static GADGET *SaveAWindowGadgets[3];
static UWORD SaveAWindowLeft = 178;
static UWORD SaveAWindowTop = 38;
static UWORD SaveAWindowWidth = 258;
static UWORD SaveAWindowHeight = 121;
static UBYTE SaveAWindowWdt[100]; /*GMD */
static UWORD SaveAWindowGTypes[] =
{
LISTVIEW_KIND,
BUTTON_KIND,
BUTTON_KIND
};
static NEWGADGET SaveAWindowNGad[] =
{
8, 18, 241, 80, (UBYTE *) "Windows", NULL, GD_WindowsLVGad, PLACETEXT_ABOVE, NULL, NULL,
8, 103, 113, 13, (UBYTE *) "IFF File", NULL, GD_SaveIFFGad, PLACETEXT_IN, NULL, NULL,
128, 103, 121, 13, (UBYTE *) "Rescan windows", NULL, GD_ResetWinGad, PLACETEXT_IN, NULL, NULL
};
static ULONG *SaveAWindowGTags[] =
{
(ULONG *) (GTLV_ShowSelected), (ULONG *) NULL, (ULONG *) (GTLV_Labels), (ULONG *) & WinList, (ULONG *) (TAG_DONE),
(ULONG *) (TAG_DONE),
(ULONG *) (TAG_DONE)
};
/*
* OpenSaveAWindowWindow() öffnet ein Fenster mit einem
* ListView und zwei Gadgets zu Auswahl eines zu speichernden
* Fensters
*/
static int
OpenSaveAWindowWindow (void)
{
NEWGADGET ng;
GADGET *g;
UWORD lc, tc;
UWORD wleft = SaveAWindowLeft, wtop = SaveAWindowTop, ww, wh;
int gl[] =
{GD_WindowsLVGad - GD_WindowsLVGad};
AdjustWindowDimensions (Scr, SaveAWindowLeft, SaveAWindowTop, SaveAWindowWidth, SaveAWindowHeight,
&wleft, &wtop, &ww, &wh);
if (!(g = CreateContext (&SaveAWindowGList)))
return 1L;
for (lc = 0, tc = 0; lc < SaveAWindow_CNT; lc++)
{
CopyMem ((char *) &SaveAWindowNGad[lc], (char *) &ng, (long) sizeof (NEWGADGET));
ng.ng_VisualInfo = VisualInfo;
ng.ng_TextAttr = Font;
ng.ng_LeftEdge = OffX + ComputeX (ng.ng_LeftEdge);
ng.ng_TopEdge = OffY + ComputeY (ng.ng_TopEdge);
ng.ng_Width = ComputeX (ng.ng_Width);
ng.ng_Height = ComputeY (ng.ng_Height);
SaveAWindowGadgets[lc] = g = CreateGadgetA ((ULONG) SaveAWindowGTypes[lc], g, &ng, (TAGITEM *) & SaveAWindowGTags[tc]);
makelabelvisible (SaveAWindowGadgets[lc]);
while (SaveAWindowGTags[tc])
tc += 2;
tc++;
if (NOT g)
return 2L;
}
strcpy (SaveAWindowWdt, get_vers (" - Save window")); /*GMD */
if (!(SaveAWindowWnd = OpenWindowTags (NULL,
WA_Left, wleft,
WA_Top, wtop,
WA_Width, ww,
WA_Height, wh,
WA_IDCMP, LISTVIEWIDCMP |
BUTTONIDCMP |
IDCMP_CLOSEWINDOW |
IDCMP_VANILLAKEY |
IDCMP_REFRESHWINDOW,
WA_Flags, WFLG_DRAGBAR |
WFLG_DEPTHGADGET |
WFLG_CLOSEGADGET |
WFLG_SMART_REFRESH |
WFLG_ACTIVATE |
WFLG_RMBTRAP,
WA_Title, SaveAWindowWdt,
WA_PubScreenFallBack, TRUE,
WA_PubScreen, Scr,
TAG_DONE)))
return 4L;
RefreshRastPort (SaveAWindowWnd, SaveAWindowGadgets, gl, 1, FALSE, SaveAWindowGList);
return NULL;
}
/*
* CreateWinList() erzeugt eine Liste von Fenstertiteln und
* Adressen
*/
static void
CreateWinList (int count)
{
ULONG lock;
WINDOW *win;
SCREEN *scr;
char help[MAXFULLNAME];
int i = 0;
DPOS;
MyFreeVec (windows);
windows = (RSYS_winlist *) MyAllocVec (count * sizeof (RSYS_winlist),
MEMF_ANY | MEMF_CLEAR, KILL);
lock = LockIBase (NULL);
for (scr = IntuitionBase->FirstScreen; scr && (i < count); scr = scr->NextScreen)
for (win = scr->FirstWindow; win && (i < count); win = win->NextWindow)
{
windows[i].node.ln_Name = windows[i].name;
windows[i].node.ln_Type = NT_USER;
windows[i].win = win;
if ((char *) win->Title)
strncpy (help, (char *) win->Title, MAXFULLNAME - 1);
else
help[0] = STRINGEND;
sprintf (windows[i].name, "0x%08lX %s", windows[i].win, help);
i++;
}
UnlockIBase (lock);
for (i = 0; i < count; i++)
AddTail (&WinList, &windows[i].node);
return;
}
/*
* ResetWinList() erneuert die Window-Liste
*/
static void
ResetWinList (void)
{
int cntwin;
DPOS;
InitListView (SaveAWindowWnd, SaveAWindowGadgets[GD_WindowsLVGad - GD_WindowsLVGad], NULL, 0);
NewList (&WinList);
cntwin = CountIntuiObjects ((int) WINDOWS);
CreateWinList (cntwin);
InitListView (SaveAWindowWnd, SaveAWindowGadgets[GD_WindowsLVGad - GD_WindowsLVGad], &WinList, 0);
EnableGadget (SaveAWindowWnd, SaveAWindowGadgets[GD_SaveIFFGad - GD_WindowsLVGad], FALSE);
return;
}
/*
* SaveWindows() bietet eine Benutzeroberfläche an und
* verwaltet die Benutzereingaben
*/
void
SaveWindows (void)
{
INTUIMESSAGE *message;
ULONG class, code;
APTR object;
NODE *clickednode = NULL;
WINDOW *printwin;
int id;
DPOS;
HandleHelp (MN_SaveWindows);
Flags.quit_sw = 0;
NewList (&WinList);
windows = NULL;
if (OpenASysWindow (OpenSaveAWindowWindow, NO_KILL))
{
PrintInfo ("Save windows", SPEAK, 0);
LockMainWindow (WIN_LOCK);
ResetWinList ();
do
{
Wait (1L << SaveAWindowWnd->UserPort->mp_SigBit);
while ((message = (INTUIMESSAGE *) GT_GetIMsg (SaveAWindowWnd->UserPort)) != NULL)
{
class = message->Class;
code = message->Code;
object = message->IAddress;
GT_ReplyIMsg (message);
switch (class)
{
case IDCMP_CLOSEWINDOW:
Flags.quit_sw = 1;
break;
case IDCMP_GADGETUP:
id = ((GADGET *) object)->GadgetID;
switch (id)
{
case GD_WindowsLVGad:
if (clickednode = GetNode (&WinList, code))
EnableGadget (SaveAWindowWnd, SaveAWindowGadgets[GD_SaveIFFGad - GD_WindowsLVGad],
TRUE);
printwin = ((RSYS_winlist *) clickednode)->win;
if (NOT (CheckWindow (printwin)))
{
ErrorHandle (clickednode->ln_Name, WINDOW_ERR, FIND_FAIL, NO_KILL);
clickednode = NULL;
ResetWinList ();
}
break;
case GD_SaveIFFGad:
if (clickednode)
{
if (GetFile (SaveAWindowWnd, "RAM:",
"RSys-Window.IFF", "#?.IFF",
"Select IFF-File for saving Window",
"Save"))
{
printwin = ((RSYS_winlist *) clickednode)->win;
if (CheckWindow (printwin))
{
if (NOT (SaveWindow ((STRPTR) _fullpath, printwin)))
ErrorHandle (_fullpath, FILE_ERR, WRITE_FAIL, NO_KILL);
}
else
ErrorHandle (clickednode->ln_Name, WINDOW_ERR, FIND_FAIL, NO_KILL);
ResetWinList ();
}
}
break;
case GD_ResetWinGad:
clickednode = NULL;
ResetWinList ();
break;
}
break;
case IDCMP_VANILLAKEY:
if ((char) code == ESC)
Flags.quit_sw = 1;
break;
}
}
}
while (NOT (Flags.quit_sw));
CloseASysWindow (&SaveAWindowWnd, &SaveAWindowGList, NULL);
MyFreeVec (windows);
LockMainWindow (WIN_UNLOCK);
}
return;
}